package com.gitee.wsl.mathematics.interpolator.ext

import com.gitee.wsl.mathematics.interpolator.Interpolate
import com.gitee.wsl.mathematics.interpolator.times
import kotlin.math.PI
import kotlin.math.pow
import kotlin.math.sin

fun Interpolate.Companion.circle(mCycles:Float) = Interpolate{pet ->
    sin(2 * mCycles * PI * pet)
}

private fun bounce(t: Double): Double {
    return t * t * 8.0f
}

val Interpolate.Companion.bounce get() = Interpolate{input ->
    // _b(t) = t * t * 8
    // bs(t) = _b(t) for t < 0.3535
    // bs(t) = _b(t - 0.54719) + 0.7 for t < 0.7408
    // bs(t) = _b(t - 0.8526) + 0.9 for t < 0.9644
    // bs(t) = _b(t - 1.0435) + 0.95 for t <= 1.0
    // b(t) = bs(t * 1.1226)
    val t = 1.1226 * input
     if (t < 0.3535f) {
        bounce(t)
    } else if (t < 0.7408f) {
        bounce(t - 0.54719f) + 0.7f
    } else if (t < 0.9644f) {
        bounce(t - 0.8526f) + 0.9f
    } else {
        bounce(t - 1.0435f) + 0.95f
    }
}

/**
 * An interpolator where the change starts backward then flings forward.
 */
fun Interpolate.Companion.anticipate(tension:Float) = Interpolate{input ->
    // a(t) = t * t * ((tension + 1) * t - tension)
    input * input * ((tension + 1) * input - tension);
}


/**
 * An interpolator where the rate of change starts out slowly and
 * then accelerates.
 */
fun Interpolate.Companion.accelerate(factor :Float, doubleFactor:Float = 2 * factor) = Interpolate{input ->
     if (factor == 1.0f) {
        input * input.value
    } else {
        input.value.pow(doubleFactor.toDouble())
    }
}

